import React, { MouseEvent } from "react";

interface OrgTreeNodeProps {
	data: any;
	node: {
		label?: string;
		expand?: string;
		children?: string;
	};
	collapsable?: boolean;
	onExpand?: (e: MouseEvent<HTMLSpanElement>, nodeData: any) => void;
	renderContent?: (data: any) => React.ReactNode;
	onClick?: (e: MouseEvent<HTMLDivElement>, nodeData: any) => void;
	labelWidth?: number;
	labelClassName?: string;
}

const isLeaf = (data: any, prop: OrgTreeNodeProps) => {
	const node = prop.node;
	// @ts-ignore
	return !(Array.isArray(data[node?.children]) && data[node?.children].length > 0);
};

export const renderNode = (data: any, prop: OrgTreeNodeProps) => {
	const node = prop.node;
	const cls = ["org-tree-node"];
	const childNodes: React.ReactNode[] = [];

	if (isLeaf(data, prop)) {
		cls.push("is-leaf");
		// @ts-ignore
	} else if (prop.collapsable && !data[node?.expand]) {
		cls.push("collapsed");
	}

	childNodes.push(renderLabel(data, prop));
	// @ts-ignore
	if (!prop.collapsable || data[node?.expand]) {
		childNodes.push(renderChildren(data.children, prop));
	}

	return (
		<div key={data.id} className={cls.join(" ")}>
			{childNodes}
		</div>
	);
};

export const renderBtn = (data: any, prop: OrgTreeNodeProps) => {
	const { onExpand } = prop;
	const node = prop.node;

	let cls = ["org-tree-node-btn"];
	// @ts-ignore
	if (data[node?.expand]) {
		cls.push("expanded");
	}

	return (
		<span
			key={data.id}
			className={cls.join(" ")}
			onClick={e => {
				e.stopPropagation();
				typeof onExpand === "function" && onExpand(e, data);
			}}
		/>
	);
};

export const renderLabel = (data: any, prop: OrgTreeNodeProps) => {
	const node = prop.node;
	// @ts-ignore
	const label = data[node?.label];
	const renderContent = prop.renderContent;
	const onClick = prop.onClick;

	const childNodes: React.ReactNode[] = [];
	if (typeof renderContent === "function") {
		let vnode = renderContent(data);

		vnode && childNodes.push(vnode);
	} else {
		childNodes.push(label);
	}

	if (prop.collapsable && !isLeaf(data, prop)) {
		childNodes.push(renderBtn(data, prop));
	}

	const cls = ["org-tree-node-label-inner"];

	let { labelWidth, labelClassName } = prop;

	if (typeof labelWidth === "number") {
		// @ts-ignore
		labelWidth += "px";
	}

	labelClassName && cls.push(labelClassName);

	return (
		<div
			key={`label_${data.id}`}
			className="org-tree-node-label"
			onClick={e => typeof onClick === "function" && onClick(e, data)}
		>
			<div key={`label_inner_${data.id}`} className={cls.join(" ")} style={{ width: labelWidth }}>
				{childNodes}
			</div>
		</div>
	);
};

export const renderChildren = (list: any[], prop: OrgTreeNodeProps) => {
	if (Array.isArray(list) && list.length) {
		const children = list.map(item => {
			return renderNode(item, prop);
		});
		return (
			<div key={`children_${children[0].key}`} className="org-tree-node-children">
				{children}
			</div>
		);
	}
	return null;
};

export const render = (props: OrgTreeNodeProps) => {
	return renderNode(props.data, props);
};

export default render;
